home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / libvlc.c next >
C/C++ Source or Header  |  2003-04-08  |  46KB  |  1,465 lines

  1. /*****************************************************************************
  2.  * libvlc.c: main libvlc source
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2002 VideoLAN
  5.  * $Id: libvlc.c,v 1.77 2003/04/08 08:35:59 massiot Exp $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *          Gildas Bazin <gbazin@netcourrier.com>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25.  
  26. /*****************************************************************************
  27.  * Pretend we are a builtin module
  28.  *****************************************************************************/
  29. #define MODULE_NAME main
  30. #define MODULE_PATH main
  31. #define __BUILTIN__
  32.  
  33. /*****************************************************************************
  34.  * Preamble
  35.  *****************************************************************************/
  36. #include <vlc/vlc.h>
  37.  
  38. #ifdef HAVE_ERRNO_H
  39. #   include <errno.h>                                              /* ENOMEM */
  40. #endif
  41. #include <stdio.h>                                              /* sprintf() */
  42. #include <string.h>                                            /* strerror() */
  43. #include <stdlib.h>                                                /* free() */
  44.  
  45. #ifndef WIN32
  46. #   include <netinet/in.h>                            /* BSD: struct in_addr */
  47. #endif
  48.  
  49. #ifdef HAVE_UNISTD_H
  50. #   include <unistd.h>
  51. #elif defined( WIN32 ) && !defined( UNDER_CE )
  52. #   include <io.h>
  53. #endif
  54.  
  55. #ifdef WIN32                       /* optind, getopt(), included in unistd.h */
  56. #   include "extras/getopt.h"
  57. #endif
  58.  
  59. #ifdef HAVE_LOCALE_H
  60. #   include <locale.h>
  61. #endif
  62.  
  63. #include "vlc_cpu.h"                                        /* CPU detection */
  64. #include "os_specific.h"
  65.  
  66. #include "error.h"
  67. #include "netutils.h"                                 /* network_ChannelJoin */
  68.  
  69. #include "stream_control.h"
  70. #include "input_ext-intf.h"
  71.  
  72. #include "vlc_playlist.h"
  73. #include "interface.h"
  74.  
  75. #include "audio_output.h"
  76.  
  77. #include "video.h"
  78. #include "video_output.h"
  79.  
  80. #include "libvlc.h"
  81.  
  82. /*****************************************************************************
  83.  * The evil global variable. We handle it with care, don't worry.
  84.  *****************************************************************************/
  85. static libvlc_t libvlc;
  86. static vlc_t *  p_static_vlc;
  87.  
  88. /*****************************************************************************
  89.  * Local prototypes
  90.  *****************************************************************************/
  91. static void SetLanguage   ( char const * );
  92. static int  GetFilenames  ( vlc_t *, int, char *[] );
  93. static void Usage         ( vlc_t *, char const *psz_module_name );
  94. static void ListModules   ( vlc_t * );
  95. static void Version       ( void );
  96.  
  97. #ifdef WIN32
  98. static void ShowConsole   ( void );
  99. #endif
  100. static int  ConsoleWidth  ( void );
  101.  
  102. /*****************************************************************************
  103.  * VLC_Version: return the libvlc version.
  104.  *****************************************************************************
  105.  * This function returns full version string (numeric version and codename).
  106.  *****************************************************************************/
  107. char const * VLC_Version( void )
  108. {
  109.     return VERSION_MESSAGE;
  110. }
  111.  
  112. /*****************************************************************************
  113.  * VLC_Error: strerror() equivalent
  114.  *****************************************************************************
  115.  * This function returns full version string (numeric version and codename).
  116.  *****************************************************************************/
  117. char const * VLC_Error( int i_err )
  118. {
  119.     return vlc_error( i_err );
  120. }
  121.  
  122. /*****************************************************************************
  123.  * VLC_Create: allocate a vlc_t structure, and initialize libvlc if needed.
  124.  *****************************************************************************
  125.  * This function allocates a vlc_t structure and returns a negative value
  126.  * in case of failure. Also, the thread system is initialized.
  127.  *****************************************************************************/
  128. int VLC_Create( void )
  129. {
  130.     int i_ret;
  131.     vlc_t * p_vlc = NULL;
  132.     vlc_value_t lockval;
  133.  
  134.     /* vlc_threads_init *must* be the first internal call! No other call is
  135.      * allowed before the thread system has been initialized. */
  136.     i_ret = vlc_threads_init( &libvlc );
  137.     if( i_ret < 0 )
  138.     {
  139.         return i_ret;
  140.     }
  141.  
  142.     /* Now that the thread system is initialized, we don't have much, but
  143.      * at least we have var_Create */
  144.     var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
  145.     var_Get( &libvlc, "libvlc", &lockval );
  146.     vlc_mutex_lock( lockval.p_address );
  147.     if( !libvlc.b_ready )
  148.     {
  149.         char *psz_env;
  150.  
  151.         /* Guess what CPU we have */
  152.         libvlc.i_cpu = CPUCapabilities();
  153.  
  154.         /* Find verbosity from VLC_VERBOSE environment variable */
  155.         psz_env = getenv( "VLC_VERBOSE" );
  156.         libvlc.i_verbose = psz_env ? atoi( psz_env ) : -1;
  157.  
  158. #ifdef HAVE_ISATTY
  159.         libvlc.b_color = isatty( 2 ); /* 2 is for stderr */
  160. #else
  161.         libvlc.b_color = VLC_FALSE;
  162. #endif
  163.  
  164.         /* Initialize message queue */
  165.         msg_Create( &libvlc );
  166.  
  167.         /* Announce who we are */
  168.         msg_Dbg( &libvlc, COPYRIGHT_MESSAGE );
  169.         msg_Dbg( &libvlc, "libvlc was configured with %s", CONFIGURE_LINE );
  170.  
  171.         /* The module bank will be initialized later */
  172.         libvlc.p_module_bank = NULL;
  173.  
  174.         libvlc.b_ready = VLC_TRUE;
  175.     }
  176.     vlc_mutex_unlock( lockval.p_address );
  177.     var_Destroy( &libvlc, "libvlc" );
  178.  
  179.     /* Allocate a vlc object */
  180.     p_vlc = vlc_object_create( &libvlc, VLC_OBJECT_VLC );
  181.     if( p_vlc == NULL )
  182.     {
  183.         return VLC_EGENERIC;
  184.     }
  185.     vlc_thread_set_priority( p_vlc, VLC_THREAD_PRIORITY_LOW );
  186.  
  187.     p_vlc->psz_object_name = "root";
  188.  
  189.     /* Initialize mutexes */
  190.     vlc_mutex_init( p_vlc, &p_vlc->config_lock );
  191.  
  192.     /* Store our newly allocated structure in the global list */
  193.     vlc_object_attach( p_vlc, &libvlc );
  194.  
  195.     /* Store data for the non-reentrant API */
  196.     p_static_vlc = p_vlc;
  197.  
  198.     return p_vlc->i_object_id;
  199. }
  200.  
  201. /*****************************************************************************
  202.  * VLC_Init: initialize a vlc_t structure.
  203.  *****************************************************************************
  204.  * This function initializes a previously allocated vlc_t structure:
  205.  *  - CPU detection
  206.  *  - gettext initialization
  207.  *  - message queue, module bank and playlist initialization
  208.  *  - configuration and commandline parsing
  209.  *****************************************************************************/
  210. int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
  211. {
  212.     char         p_capabilities[200];
  213.     char *       p_tmp;
  214.     char *       psz_modules;
  215.     char *       psz_parser;
  216.     vlc_bool_t   b_exit = VLC_FALSE;
  217.     vlc_t *      p_vlc;
  218.     module_t    *p_help_module;
  219.     playlist_t  *p_playlist;
  220.     vlc_value_t  lockval;
  221.  
  222.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  223.  
  224.     if( !p_vlc )
  225.     {
  226.         return VLC_ENOOBJ;
  227.     }
  228.  
  229.     /*
  230.      * System specific initialization code
  231.      */
  232.     system_Init( p_vlc, &i_argc, ppsz_argv );
  233.  
  234.     /* Get the executable name (similar to the basename command) */
  235.     if( i_argc > 0 )
  236.     {
  237.         p_vlc->psz_object_name = p_tmp = ppsz_argv[ 0 ];
  238.         while( *p_tmp )
  239.         {
  240.             if( *p_tmp == '/' ) p_vlc->psz_object_name = ++p_tmp;
  241.             else ++p_tmp;
  242.         }
  243.     }
  244.     else
  245.     {
  246.         p_vlc->psz_object_name = "vlc";
  247.     }
  248.  
  249.     /*
  250.      * Support for gettext
  251.      */
  252.     SetLanguage( "" );
  253.  
  254.     /* Translate "C" to the language code: "fr", "en_GB", "nl", "ru"... */
  255.     msg_Dbg( p_vlc, "translation test: code is \"%s\"", _("C") );
  256.  
  257.     /* Initialize the module bank and load the configuration of the
  258.      * main module. We need to do this at this stage to be able to display
  259.      * a short help if required by the user. (short help == main module
  260.      * options) */
  261.     var_Create( &libvlc, "libvlc", VLC_VAR_MUTEX );
  262.     var_Get( &libvlc, "libvlc", &lockval );
  263.     vlc_mutex_lock( lockval.p_address );
  264.     if( libvlc.p_module_bank == NULL )
  265.     {
  266.         module_InitBank( &libvlc );
  267.         module_LoadMain( &libvlc );
  268.     }
  269.     vlc_mutex_unlock( lockval.p_address );
  270.     var_Destroy( &libvlc, "libvlc" );
  271.  
  272.     /* Hack: insert the help module here */
  273.     p_help_module = vlc_object_create( p_vlc, VLC_OBJECT_MODULE );
  274.     if( p_help_module == NULL )
  275.     {
  276.         //module_EndBank( p_vlc );
  277.         if( i_object ) vlc_object_release( p_vlc );
  278.         return VLC_EGENERIC;
  279.     }
  280.     p_help_module->psz_object_name = "help";
  281.     config_Duplicate( p_help_module, p_help_config );
  282.     vlc_object_attach( p_help_module, libvlc.p_module_bank );
  283.     /* End hack */
  284.  
  285.     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE ) )
  286.     {
  287.         vlc_object_detach( p_help_module );
  288.         config_Free( p_help_module );
  289.         vlc_object_destroy( p_help_module );
  290.         //module_EndBank( p_vlc );
  291.         if( i_object ) vlc_object_release( p_vlc );
  292.         return VLC_EGENERIC;
  293.     }
  294.  
  295.     /* Check for short help option */
  296.     if( config_GetInt( p_vlc, "help" ) )
  297.     {
  298.         fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
  299.                          p_vlc->psz_object_name );
  300.         Usage( p_vlc, "main" );
  301.         Usage( p_vlc, "help" );
  302.         b_exit = VLC_TRUE;
  303.     }
  304.     /* Check for version option */
  305.     else if( config_GetInt( p_vlc, "version" ) )
  306.     {
  307.         Version();
  308.         b_exit = VLC_TRUE;
  309.     }
  310.  
  311.     /* Hack: remove the help module here */
  312.     vlc_object_detach( p_help_module );
  313.     /* End hack */
  314.  
  315.     if( b_exit )
  316.     {
  317.         config_Free( p_help_module );
  318.         vlc_object_destroy( p_help_module );
  319.         //module_EndBank( p_vlc );
  320.         if( i_object ) vlc_object_release( p_vlc );
  321.         return VLC_EEXIT;
  322.     }
  323.  
  324.     /* Check for translation config option */
  325. #if defined( ENABLE_NLS ) \
  326.      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  327.  
  328.     /* This ain't really nice to have to reload the config here but it seems
  329.      * the only way to do it. */
  330.     p_vlc->psz_homedir = config_GetHomeDir();
  331.     config_LoadConfigFile( p_vlc, "main" );
  332.     config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_TRUE );
  333.  
  334.     if( !config_GetInt( p_vlc, "translation" ) )
  335.     {
  336.         /* Reset the default domain */
  337.         SetLanguage( "C" );
  338.  
  339.         textdomain( "dummy" );
  340.  
  341.         module_EndBank( p_vlc );
  342.         module_InitBank( &libvlc );
  343.         module_LoadMain( &libvlc );
  344.     }
  345. #endif
  346.  
  347.     /*
  348.      * Load the builtins and plugins into the module_bank.
  349.      * We have to do it before config_Load*() because this also gets the
  350.      * list of configuration options exported by each module and loads their
  351.      * default values.
  352.      */
  353.     module_LoadBuiltins( &libvlc );
  354.     module_LoadPlugins( &libvlc );
  355.     msg_Dbg( p_vlc, "module bank initialized, found %i modules",
  356.                     libvlc.p_module_bank->i_children );
  357.  
  358.     /* Hack: insert the help module here */
  359.     vlc_object_attach( p_help_module, libvlc.p_module_bank );
  360.     /* End hack */
  361.  
  362.     /* Check for help on modules */
  363.     if( (p_tmp = config_GetPsz( p_vlc, "module" )) )
  364.     {
  365.         Usage( p_vlc, p_tmp );
  366.         free( p_tmp );
  367.         b_exit = VLC_TRUE;
  368.     }
  369.     /* Check for long help option */
  370.     else if( config_GetInt( p_vlc, "longhelp" ) )
  371.     {
  372.         Usage( p_vlc, NULL );
  373.         b_exit = VLC_TRUE;
  374.     }
  375.     /* Check for module list option */
  376.     else if( config_GetInt( p_vlc, "list" ) )
  377.     {
  378.         ListModules( p_vlc );
  379.         b_exit = VLC_TRUE;
  380.     }
  381.  
  382.     /* Hack: remove the help module here */
  383.     vlc_object_detach( p_help_module );
  384.     config_Free( p_help_module );
  385.     vlc_object_destroy( p_help_module );
  386.     /* End hack */
  387.  
  388.     if( b_exit )
  389.     {
  390.         //module_EndBank( p_vlc );
  391.         if( i_object ) vlc_object_release( p_vlc );
  392.         return VLC_EEXIT;
  393.     }
  394.  
  395.     /*
  396.      * Override default configuration with config file settings
  397.      */
  398.     p_vlc->psz_homedir = config_GetHomeDir();
  399.     config_LoadConfigFile( p_vlc, NULL );
  400.  
  401.     /*
  402.      * Override configuration with command line settings
  403.      */
  404.     if( config_LoadCmdLine( p_vlc, &i_argc, ppsz_argv, VLC_FALSE ) )
  405.     {
  406. #ifdef WIN32
  407.         ShowConsole();
  408.         /* Pause the console because it's destroyed when we exit */
  409.         fprintf( stderr, "The command line options couldn't be loaded, check "
  410.                  "that they are valid.\nPress the RETURN key to continue..." );
  411.         getchar();
  412. #endif
  413.         //module_EndBank( p_vlc );
  414.         if( i_object ) vlc_object_release( p_vlc );
  415.         return VLC_EGENERIC;
  416.     }
  417.  
  418.     /*
  419.      * System specific configuration
  420.      */
  421.     system_Configure( p_vlc );
  422.  
  423.     /*
  424.      * Message queue options
  425.      */
  426.     if( config_GetInt( p_vlc, "quiet" ) )
  427.     {
  428.         libvlc.i_verbose = -1;
  429.     }
  430.     else
  431.     {
  432.         int i_tmp = config_GetInt( p_vlc, "verbose" );
  433.         if( i_tmp >= 0 )
  434.         {
  435.             libvlc.i_verbose = __MIN( i_tmp, 2 );
  436.         }
  437.     }
  438.     libvlc.b_color = libvlc.b_color || config_GetInt( p_vlc, "color" );
  439.  
  440.     /*
  441.      * Output messages that may still be in the queue
  442.      */
  443.     msg_Flush( p_vlc );
  444.  
  445.     /* p_vlc initialization. FIXME ? */
  446.     p_vlc->i_desync = config_GetInt( p_vlc, "desync" ) * (mtime_t)1000;
  447.  
  448. #if defined( __i386__ )
  449.     if( !config_GetInt( p_vlc, "mmx" ) )
  450.         libvlc.i_cpu &= ~CPU_CAPABILITY_MMX;
  451.     if( !config_GetInt( p_vlc, "3dn" ) )
  452.         libvlc.i_cpu &= ~CPU_CAPABILITY_3DNOW;
  453.     if( !config_GetInt( p_vlc, "mmxext" ) )
  454.         libvlc.i_cpu &= ~CPU_CAPABILITY_MMXEXT;
  455.     if( !config_GetInt( p_vlc, "sse" ) )
  456.         libvlc.i_cpu &= ~CPU_CAPABILITY_SSE;
  457. #endif
  458. #if defined( __powerpc__ ) || defined( SYS_DARWIN )
  459.     if( !config_GetInt( p_vlc, "altivec" ) )
  460.         libvlc.i_cpu &= ~CPU_CAPABILITY_ALTIVEC;
  461. #endif
  462.  
  463. #define PRINT_CAPABILITY( capability, string )                              \
  464.     if( libvlc.i_cpu & capability )                                         \
  465.     {                                                                       \
  466.         strncat( p_capabilities, string " ",                                \
  467.                  sizeof(p_capabilities) - strlen(p_capabilities) );         \
  468.         p_capabilities[sizeof(p_capabilities) - 1] = '\0';                  \
  469.     }
  470.  
  471.     p_capabilities[0] = '\0';
  472.     PRINT_CAPABILITY( CPU_CAPABILITY_486, "486" );
  473.     PRINT_CAPABILITY( CPU_CAPABILITY_586, "586" );
  474.     PRINT_CAPABILITY( CPU_CAPABILITY_PPRO, "Pentium Pro" );
  475.     PRINT_CAPABILITY( CPU_CAPABILITY_MMX, "MMX" );
  476.     PRINT_CAPABILITY( CPU_CAPABILITY_3DNOW, "3DNow!" );
  477.     PRINT_CAPABILITY( CPU_CAPABILITY_MMXEXT, "MMXEXT" );
  478.     PRINT_CAPABILITY( CPU_CAPABILITY_SSE, "SSE" );
  479.     PRINT_CAPABILITY( CPU_CAPABILITY_ALTIVEC, "AltiVec" );
  480.     PRINT_CAPABILITY( CPU_CAPABILITY_FPU, "FPU" );
  481.     msg_Dbg( p_vlc, "CPU has capabilities %s", p_capabilities );
  482.  
  483.     /*
  484.      * Choose the best memcpy module
  485.      */
  486.     p_vlc->p_memcpy_module = module_Need( p_vlc, "memcpy", "$memcpy" );
  487.  
  488.     if( p_vlc->pf_memcpy == NULL )
  489.     {
  490.         p_vlc->pf_memcpy = memcpy;
  491.     }
  492.  
  493.     if( p_vlc->pf_memset == NULL )
  494.     {
  495.         p_vlc->pf_memset = memset;
  496.     }
  497.  
  498.     /*
  499.      * Initialize shared resources and libraries
  500.      */
  501.     if( config_GetInt( p_vlc, "network-channel" )
  502.          && network_ChannelCreate( p_vlc ) )
  503.     {
  504.         /* On error during Channels initialization, switch off channels */
  505.         msg_Warn( p_vlc,
  506.                   "channels initialization failed, deactivating channels" );
  507.         config_PutInt( p_vlc, "network-channel", VLC_FALSE );
  508.     }
  509.  
  510.     /*
  511.      * Initialize playlist and get commandline files
  512.      */
  513.     p_playlist = playlist_Create( p_vlc );
  514.     if( !p_playlist )
  515.     {
  516.         msg_Err( p_vlc, "playlist initialization failed" );
  517.         if( p_vlc->p_memcpy_module != NULL )
  518.         {
  519.             module_Unneed( p_vlc, p_vlc->p_memcpy_module );
  520.         }
  521.         //module_EndBank( p_vlc );
  522.         if( i_object ) vlc_object_release( p_vlc );
  523.         return VLC_EGENERIC;
  524.     }
  525.  
  526.     /*
  527.      * Load background interfaces
  528.      */
  529.     psz_modules = config_GetPsz( p_vlc, "extraintf" );
  530.     psz_parser = psz_modules;
  531.     while ( psz_parser && *psz_parser )
  532.     {
  533.         char *psz_module, *psz_temp;
  534.         psz_module = psz_parser;
  535.         psz_parser = strchr( psz_module, ',' );
  536.         if ( psz_parser )
  537.         {
  538.             *psz_parser = '\0';
  539.             psz_parser++;
  540.         }
  541.         psz_temp = (char *)malloc( strlen(psz_module) + sizeof(",none") );
  542.         if( psz_temp )
  543.         {
  544.             sprintf( psz_temp, "%s,none", psz_module );
  545.             VLC_AddIntf( 0, psz_temp, VLC_FALSE );
  546.             free( psz_temp );
  547.         }
  548.     }
  549.     if ( psz_modules )
  550.     {
  551.         free( psz_modules );
  552.     }
  553.  
  554.     /*
  555.      * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin
  556.      */
  557.     var_Create( p_vlc, "drawable", VLC_VAR_INTEGER );
  558.  
  559.     /*
  560.      * Get input filenames given as commandline arguments
  561.      */
  562.     GetFilenames( p_vlc, i_argc, ppsz_argv );
  563.  
  564.     if( i_object ) vlc_object_release( p_vlc );
  565.     return VLC_SUCCESS;
  566. }
  567.  
  568. /*****************************************************************************
  569.  * VLC_AddIntf: add an interface
  570.  *****************************************************************************
  571.  * This function opens an interface plugin and runs it. If b_block is set
  572.  * to 0, VLC_AddIntf will return immediately and let the interface run in a
  573.  * separate thread. If b_block is set to 1, VLC_AddIntf will continue until
  574.  * user requests to quit.
  575.  *****************************************************************************/
  576. int VLC_AddIntf( int i_object, char const *psz_module, vlc_bool_t b_block )
  577. {
  578.     int i_err;
  579.     intf_thread_t *p_intf;
  580.     vlc_t *p_vlc;
  581.  
  582.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  583.  
  584.     if( !p_vlc )
  585.     {
  586.         return VLC_ENOOBJ;
  587.     }
  588.  
  589.     /* Try to create the interface */
  590.     p_intf = intf_Create( p_vlc, psz_module ? psz_module : "$intf" );
  591.  
  592.     if( p_intf == NULL )
  593.     {
  594.         msg_Err( p_vlc, "interface \"%s\" initialization failed", psz_module );
  595.         if( i_object ) vlc_object_release( p_vlc );
  596.         return VLC_EGENERIC;
  597.     }
  598.  
  599.     /* Try to run the interface */
  600.     p_intf->b_block = b_block;
  601.     i_err = intf_RunThread( p_intf );
  602.     if( i_err )
  603.     {
  604.         vlc_object_detach( p_intf );
  605.         intf_Destroy( p_intf );
  606.         if( i_object ) vlc_object_release( p_vlc );
  607.         return i_err;
  608.     }
  609.  
  610.     if( i_object ) vlc_object_release( p_vlc );
  611.     return VLC_SUCCESS;
  612. }
  613.  
  614. /*****************************************************************************
  615.  * VLC_Destroy: stop playing and destroy everything.
  616.  *****************************************************************************
  617.  * This function requests the running threads to finish, waits for their
  618.  * termination, and destroys their structure.
  619.  *****************************************************************************/
  620. int VLC_Destroy( int i_object )
  621. {
  622.     vlc_t *p_vlc;
  623.  
  624.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  625.  
  626.     if( !p_vlc )
  627.     {
  628.         return VLC_ENOOBJ;
  629.     }
  630.  
  631.     /*
  632.      * Go back into channel 0 which is the network
  633.      */
  634.     if( config_GetInt( p_vlc, "network-channel" ) && p_vlc->p_channel )
  635.     {
  636.         network_ChannelJoin( p_vlc, COMMON_CHANNEL );
  637.     }
  638.  
  639.     /*
  640.      * Free allocated memory
  641.      */
  642.     if( p_vlc->p_memcpy_module )
  643.     {
  644.         module_Unneed( p_vlc, p_vlc->p_memcpy_module );
  645.         p_vlc->p_memcpy_module = NULL;
  646.     }
  647.  
  648.     if( p_vlc->psz_homedir )
  649.     {
  650.         free( p_vlc->psz_homedir );
  651.         p_vlc->psz_homedir = NULL;
  652.     }
  653.  
  654.     /*
  655.      * XXX: Free module bank !
  656.      */
  657.     //module_EndBank( p_vlc );
  658.  
  659.     /*
  660.      * System specific cleaning code
  661.      */
  662.     system_End( p_vlc );
  663.  
  664.     /* Destroy mutexes */
  665.     vlc_mutex_destroy( &p_vlc->config_lock );
  666.  
  667.     vlc_object_detach( p_vlc );
  668.  
  669.     /* Release object before destroying it */
  670.     if( i_object ) vlc_object_release( p_vlc );
  671.  
  672.     vlc_object_destroy( p_vlc );
  673.  
  674.     /* Stop thread system: last one out please shut the door! */
  675.     vlc_threads_end( &libvlc );
  676.  
  677.     return VLC_SUCCESS;
  678. }
  679.  
  680. /*****************************************************************************
  681.  * VLC_Die: ask vlc to die.
  682.  *****************************************************************************
  683.  * This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
  684.  * task. It is your duty to call vlc_end and VLC_Destroy afterwards.
  685.  *****************************************************************************/
  686. int VLC_Die( int i_object )
  687. {
  688.     vlc_t *p_vlc;
  689.  
  690.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  691.  
  692.     if( !p_vlc )
  693.     {
  694.         return VLC_ENOOBJ;
  695.     }
  696.  
  697.     p_vlc->b_die = VLC_TRUE;
  698.  
  699.     if( i_object ) vlc_object_release( p_vlc );
  700.     return VLC_SUCCESS;
  701. }
  702.  
  703. /*****************************************************************************
  704.  * VLC_AddTarget: adds a target for playing.
  705.  *****************************************************************************
  706.  * This function adds psz_target to the current playlist. If a playlist does
  707.  * not exist, it will create one.
  708.  *****************************************************************************/
  709. int VLC_AddTarget( int i_object, char const *psz_target, int i_mode, int i_pos )
  710. {
  711.     int i_err;
  712.     playlist_t *p_playlist;
  713.     vlc_t *p_vlc;
  714.  
  715.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  716.  
  717.     if( !p_vlc )
  718.     {
  719.         return VLC_ENOOBJ;
  720.     }
  721.  
  722.     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
  723.  
  724.     if( p_playlist == NULL )
  725.     {
  726.         msg_Dbg( p_vlc, "no playlist present, creating one" );
  727.         p_playlist = playlist_Create( p_vlc );
  728.  
  729.         if( p_playlist == NULL )
  730.         {
  731.             if( i_object ) vlc_object_release( p_vlc );
  732.             return VLC_EGENERIC;
  733.         }
  734.  
  735.         vlc_object_yield( p_playlist );
  736.     }
  737.  
  738.     i_err = playlist_Add( p_playlist, psz_target, i_mode, i_pos );
  739.  
  740.     vlc_object_release( p_playlist );
  741.  
  742.     if( i_object ) vlc_object_release( p_vlc );
  743.     return i_err;
  744. }
  745.  
  746. /*****************************************************************************
  747.  * VLC_Set: set a vlc variable
  748.  *****************************************************************************
  749.  *
  750.  *****************************************************************************/
  751. int VLC_Set( int i_object, char const *psz_var, vlc_value_t value )
  752. {
  753.     vlc_t *p_vlc;
  754.     int i_ret;
  755.  
  756.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  757.  
  758.     if( !p_vlc )
  759.     {
  760.         return VLC_ENOOBJ;
  761.     }
  762.  
  763.     /* FIXME: Temporary hack for Mozilla, if variable starts with conf:: then
  764.      * we handle it as a configuration variable. Don't tell Gildas :) -- sam */
  765.     if( !strncmp( psz_var, "conf::", 6 ) )
  766.     {
  767.         module_config_t *p_item;
  768.         char const *psz_newvar = psz_var + 6;
  769.  
  770.         p_item = config_FindConfig( VLC_OBJECT(p_vlc), psz_newvar );
  771.  
  772.         if( p_item )
  773.         {
  774.             switch( p_item->i_type )
  775.             {
  776.                 case CONFIG_ITEM_BOOL:
  777.                     config_PutInt( p_vlc, psz_newvar, value.b_bool );
  778.                     break;
  779.                 case CONFIG_ITEM_INTEGER:
  780.                     config_PutInt( p_vlc, psz_newvar, value.i_int );
  781.                     break;
  782.                 case CONFIG_ITEM_FLOAT:
  783.                     config_PutFloat( p_vlc, psz_newvar, value.f_float );
  784.                     break;
  785.                 default:
  786.                     config_PutPsz( p_vlc, psz_newvar, value.psz_string );
  787.                     break;
  788.             }
  789.             if( i_object ) vlc_object_release( p_vlc );
  790.             return VLC_SUCCESS;
  791.         }
  792.     }
  793.  
  794.     i_ret = var_Set( p_vlc, psz_var, value );
  795.  
  796.     if( i_object ) vlc_object_release( p_vlc );
  797.     return i_ret;
  798. }
  799.  
  800. /*****************************************************************************
  801.  * VLC_Get: get a vlc variable
  802.  *****************************************************************************
  803.  *
  804.  *****************************************************************************/
  805. int VLC_Get( int i_object, char const *psz_var, vlc_value_t *p_value )
  806. {
  807.     vlc_t *p_vlc;
  808.     int i_ret;
  809.  
  810.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  811.  
  812.     if( !p_vlc )
  813.     {
  814.         return VLC_ENOOBJ;
  815.     }
  816.  
  817.     i_ret = var_Get( p_vlc, psz_var, p_value );
  818.  
  819.     if( i_object ) vlc_object_release( p_vlc );
  820.     return i_ret;
  821. }
  822.  
  823. /* FIXME: temporary hacks */
  824.  
  825. /*****************************************************************************
  826.  * VLC_Play: play
  827.  *****************************************************************************/
  828. int VLC_Play( int i_object )
  829. {
  830.     playlist_t * p_playlist;
  831.     vlc_t *p_vlc;
  832.  
  833.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  834.  
  835.     /* Check that the handle is valid */
  836.     if( !p_vlc )
  837.     {
  838.         return VLC_ENOOBJ;
  839.     }
  840.  
  841.     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
  842.  
  843.     if( !p_playlist )
  844.     {
  845.         if( i_object ) vlc_object_release( p_vlc );
  846.         return VLC_ENOOBJ;
  847.     }
  848.  
  849.     vlc_mutex_lock( &p_playlist->object_lock );
  850.     if( p_playlist->i_size )
  851.     {
  852.         vlc_mutex_unlock( &p_playlist->object_lock );
  853.         playlist_Play( p_playlist );
  854.     }
  855.     else
  856.     {
  857.         vlc_mutex_unlock( &p_playlist->object_lock );
  858.     }
  859.  
  860.     vlc_object_release( p_playlist );
  861.  
  862.     if( i_object ) vlc_object_release( p_vlc );
  863.     return VLC_SUCCESS;
  864. }
  865.  
  866. /*****************************************************************************
  867.  * VLC_Stop: stop
  868.  *****************************************************************************/
  869. int VLC_Stop( int i_object )
  870. {
  871.     intf_thread_t *   p_intf;
  872.     playlist_t    *   p_playlist;
  873.     vout_thread_t *   p_vout;
  874.     aout_instance_t * p_aout;
  875.     vlc_t *p_vlc;
  876.  
  877.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  878.  
  879.     /* Check that the handle is valid */
  880.     if( !p_vlc )
  881.     {
  882.         return VLC_ENOOBJ;
  883.     }
  884.  
  885.     /*
  886.      * Ask the interfaces to stop and destroy them
  887.      */
  888.     msg_Dbg( p_vlc, "removing all interfaces" );
  889.     while( (p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_CHILD )) )
  890.     {
  891.         intf_StopThread( p_intf );
  892.         vlc_object_detach( p_intf );
  893.         vlc_object_release( p_intf );
  894.         intf_Destroy( p_intf );
  895.     }
  896.  
  897.     /*
  898.      * Free playlists
  899.      */
  900.     msg_Dbg( p_vlc, "removing all playlists" );
  901.     while( (p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST,
  902.                                           FIND_CHILD )) )
  903.     {
  904.         vlc_object_detach( p_playlist );
  905.         vlc_object_release( p_playlist );
  906.         playlist_Destroy( p_playlist );
  907.     }
  908.  
  909.     /*
  910.      * Free video outputs
  911.      */
  912.     msg_Dbg( p_vlc, "removing all video outputs" );
  913.     while( (p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD )) )
  914.     {
  915.         vlc_object_detach( p_vout );
  916.         vlc_object_release( p_vout );
  917.         vout_Destroy( p_vout );
  918.     }
  919.  
  920.     /*
  921.      * Free audio outputs
  922.      */
  923.     msg_Dbg( p_vlc, "removing all audio outputs" );
  924.     while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
  925.     {
  926.         vlc_object_detach( (vlc_object_t *)p_aout );
  927.         vlc_object_release( (vlc_object_t *)p_aout );
  928.         aout_Delete( p_aout );
  929.     }
  930.  
  931.     if( i_object ) vlc_object_release( p_vlc );
  932.     return VLC_SUCCESS;
  933. }
  934.  
  935. /*****************************************************************************
  936.  * VLC_Pause: toggle pause
  937.  *****************************************************************************/
  938. int VLC_Pause( int i_object )
  939. {
  940.     input_thread_t *p_input;
  941.     vlc_t *p_vlc;
  942.  
  943.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  944.  
  945.     if( !p_vlc )
  946.     {
  947.         return VLC_ENOOBJ;
  948.     }
  949.  
  950.     p_input = vlc_object_find( p_vlc, VLC_OBJECT_INPUT, FIND_CHILD );
  951.  
  952.     if( !p_input )
  953.     {
  954.         if( i_object ) vlc_object_release( p_vlc );
  955.         return VLC_ENOOBJ;
  956.     }
  957.  
  958.     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
  959.     vlc_object_release( p_input );
  960.  
  961.     if( i_object ) vlc_object_release( p_vlc );
  962.     return VLC_SUCCESS;
  963. }
  964.  
  965. /*****************************************************************************
  966.  * VLC_FullScreen: toggle fullscreen mode
  967.  *****************************************************************************/
  968. int VLC_FullScreen( int i_object )
  969. {
  970.     vout_thread_t *p_vout;
  971.     vlc_t *p_vlc;
  972.  
  973.     p_vlc = i_object ? vlc_object_get( &libvlc, i_object ) : p_static_vlc;
  974.  
  975.     if( !p_vlc )
  976.     {
  977.         return VLC_ENOOBJ;
  978.     }
  979.  
  980.     p_vout = vlc_object_find( p_vlc, VLC_OBJECT_VOUT, FIND_CHILD );
  981.  
  982.     if( !p_vout )
  983.     {
  984.         if( i_object ) vlc_object_release( p_vlc );
  985.         return VLC_ENOOBJ;
  986.     }
  987.  
  988.     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
  989.     vlc_object_release( p_vout );
  990.  
  991.     if( i_object ) vlc_object_release( p_vlc );
  992.     return VLC_SUCCESS;
  993. }
  994.  
  995. /* following functions are local */
  996.  
  997. /*****************************************************************************
  998.  * SetLanguage: set the interface language.
  999.  *****************************************************************************
  1000.  * We set the LC_MESSAGES locale category for interface messages and buttons,
  1001.  * as well as the LC_CTYPE category for string sorting and possible wide
  1002.  * character support.
  1003.  *****************************************************************************/
  1004. static void SetLanguage ( char const *psz_lang )
  1005. {
  1006. #if defined( ENABLE_NLS ) \
  1007.      && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
  1008.  
  1009.     char *          psz_path;
  1010. #if defined( SYS_DARWIN ) || defined ( WIN32 )
  1011.     char            psz_tmp[1024];
  1012. #endif
  1013.  
  1014. #   if defined( HAVE_INCLUDED_GETTEXT ) && !defined( HAVE_LC_MESSAGES )
  1015.     if( *psz_lang )
  1016.     {
  1017.         /* We set LC_ALL manually because it is the only way to set
  1018.          * the language at runtime under eg. Windows. Beware that this
  1019.          * makes the environment unconsistent when libvlc is unloaded and
  1020.          * should probably be moved to a safer place like vlc.c. */
  1021.         static char psz_lcall[20];
  1022.         snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
  1023.         psz_lcall[19] = '\0';
  1024.         putenv( psz_lcall );
  1025.     }
  1026. #   endif
  1027.  
  1028.     if( psz_lang && !*psz_lang )
  1029.     {
  1030. #   if defined( HAVE_LC_MESSAGES )
  1031.         setlocale( LC_MESSAGES, psz_lang );
  1032. #   endif
  1033.         setlocale( LC_CTYPE, psz_lang );
  1034.     }
  1035.     else
  1036.     {
  1037.         setlocale( LC_ALL, psz_lang );
  1038. #ifdef SYS_DARWIN
  1039.         /* I need that under Darwin, please check it doesn't disturb
  1040.          * other platforms. --Meuuh */
  1041.         setenv( "LANG", psz_lang, 1 );
  1042. #endif
  1043.     }
  1044.  
  1045.     /* Specify where to find the locales for current domain */
  1046. #if !defined( SYS_DARWIN ) && !defined( WIN32 )
  1047.     psz_path = LOCALEDIR;
  1048. #else
  1049.     snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
  1050.               "locale" );
  1051.     psz_path = psz_tmp;
  1052. #endif
  1053.     if( !bindtextdomain( PACKAGE, psz_path ) )
  1054.     {
  1055.         fprintf( stderr, "warning: no domain %s in directory %s\n",
  1056.                  PACKAGE, psz_path );
  1057.     }
  1058.  
  1059.     /* Set the default domain */
  1060.     textdomain( PACKAGE );
  1061. #endif
  1062. }
  1063.  
  1064. /*****************************************************************************
  1065.  * GetFilenames: parse command line options which are not flags
  1066.  *****************************************************************************
  1067.  * Parse command line for input files.
  1068.  *****************************************************************************/
  1069. static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
  1070. {
  1071.     int i_opt;
  1072.  
  1073.     /* We assume that the remaining parameters are filenames */
  1074.     for( i_opt = i_argc - 1; i_opt > optind; i_opt-- )
  1075.     {
  1076.         /* TODO: write an internal function of this one, to avoid
  1077.          *       unnecessary lookups. */
  1078.         VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ i_opt ],
  1079.                        PLAYLIST_INSERT, 0 );
  1080.     }
  1081.  
  1082.     /* If there is at least one target, play it */
  1083.     if( i_argc > optind )
  1084.     {
  1085.         VLC_AddTarget( p_vlc->i_object_id, ppsz_argv[ optind ],
  1086.                        PLAYLIST_INSERT | PLAYLIST_GO, 0 );
  1087.     }
  1088.  
  1089.     return VLC_SUCCESS;
  1090. }
  1091.  
  1092. /*****************************************************************************
  1093.  * Usage: print program usage
  1094.  *****************************************************************************
  1095.  * Print a short inline help. Message interface is initialized at this stage.
  1096.  *****************************************************************************/
  1097. static void Usage( vlc_t *p_this, char const *psz_module_name )
  1098. {
  1099. #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
  1100.     /* short option ------'    |     | | | |  | |
  1101.      * option name ------------'     | | | |  | |
  1102.      * <bra -------------------------' | | |  | |
  1103.      * option type or "" --------------' | |  | |
  1104.      * ket> -----------------------------' |  | |
  1105.      * padding spaces ---------------------'  | |
  1106.      * comment -------------------------------' |
  1107.      * comment suffix --------------------------'
  1108.      *
  1109.      * The purpose of having bra and ket is that we might i18n them as well.
  1110.      */
  1111. #define LINE_START 8
  1112. #define PADDING_SPACES 25
  1113.     vlc_list_t *p_list;
  1114.     module_t *p_parser;
  1115.     module_config_t *p_item;
  1116.     char psz_spaces[PADDING_SPACES+LINE_START+1];
  1117.     char psz_format[sizeof(FORMAT_STRING)];
  1118.     char psz_buffer[1000];
  1119.     char psz_short[4];
  1120.     int i_index;
  1121.     int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
  1122.  
  1123.     memset( psz_spaces, ' ', PADDING_SPACES+LINE_START );
  1124.     psz_spaces[PADDING_SPACES+LINE_START] = '\0';
  1125.  
  1126.     strcpy( psz_format, FORMAT_STRING );
  1127.  
  1128. #ifdef WIN32
  1129.     ShowConsole();
  1130. #endif
  1131.  
  1132.     /* List all modules */
  1133.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  1134.  
  1135.     /* Enumerate the config for each module */
  1136.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  1137.     {
  1138.         vlc_bool_t b_help_module;
  1139.  
  1140.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  1141.  
  1142.         if( psz_module_name && strcmp( psz_module_name,
  1143.                                        p_parser->psz_object_name ) )
  1144.         {
  1145.             continue;
  1146.         }
  1147.  
  1148.         /* Ignore modules without config options */
  1149.         if( !p_parser->i_config_items )
  1150.         {
  1151.             continue;
  1152.         }
  1153.  
  1154.         b_help_module = !strcmp( "help", p_parser->psz_object_name );
  1155.  
  1156.         /* Print module options */
  1157.         for( p_item = p_parser->p_config;
  1158.              p_item->i_type != CONFIG_HINT_END;
  1159.              p_item++ )
  1160.         {
  1161.             char *psz_text;
  1162.             char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
  1163.             char *psz_suf = "", *psz_prefix = NULL;
  1164.             int i;
  1165.             if ( p_item->b_advanced && !config_GetInt( p_this, "advanced" ))
  1166.             {
  1167.                 continue;
  1168.             }
  1169.             switch( p_item->i_type )
  1170.             {
  1171.             case CONFIG_HINT_CATEGORY:
  1172.             case CONFIG_HINT_USAGE:
  1173.                 fprintf( stdout, " %s\n", p_item->psz_text );
  1174.                 break;
  1175.  
  1176.             case CONFIG_ITEM_STRING:
  1177.             case CONFIG_ITEM_FILE:
  1178.             case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
  1179.                 if( !p_item->ppsz_list )
  1180.                 {
  1181.                     psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
  1182.                     break;
  1183.                 }
  1184.                 else
  1185.                 {
  1186.                     psz_bra = " {";
  1187.                     psz_type = psz_buffer;
  1188.                     psz_type[0] = '\0';
  1189.                     for( i = 0; p_item->ppsz_list[i]; i++ )
  1190.                     {
  1191.                         if( i ) strcat( psz_type, "," );
  1192.                         strcat( psz_type, p_item->ppsz_list[i] );
  1193.                     }
  1194.                     psz_ket = "}";
  1195.                     break;
  1196.                 }
  1197.             case CONFIG_ITEM_INTEGER:
  1198.                 psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
  1199.                 break;
  1200.             case CONFIG_ITEM_FLOAT:
  1201.                 psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
  1202.                 break;
  1203.             case CONFIG_ITEM_BOOL:
  1204.                 psz_bra = ""; psz_type = ""; psz_ket = "";
  1205.                 if( !b_help_module )
  1206.                 {
  1207.                     psz_suf = p_item->i_value ? _(" (default enabled)") :
  1208.                                                 _(" (default disabled)");
  1209.                 }
  1210.                 break;
  1211.             }
  1212.  
  1213.             if( !psz_type )
  1214.             {
  1215.                 continue;
  1216.             }
  1217.  
  1218.             /* Add short option if any */
  1219.             if( p_item->i_short )
  1220.             {
  1221.                 sprintf( psz_short, "-%c,", p_item->i_short );
  1222.             }
  1223.             else
  1224.             {
  1225.                 strcpy( psz_short, "   " );
  1226.             }
  1227.  
  1228.             i = PADDING_SPACES - strlen( p_item->psz_name )
  1229.                  - strlen( psz_bra ) - strlen( psz_type )
  1230.                  - strlen( psz_ket ) - 1;
  1231.  
  1232.             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
  1233.             {
  1234.                 /* If option is of type --foo-bar, we print its counterpart
  1235.                  * as --no-foo-bar, but if it is of type --foobar (without
  1236.                  * dashes in the name) we print it as --nofoobar. Both
  1237.                  * values are of course valid, only the display changes. */
  1238.                 psz_prefix = strchr( p_item->psz_name, '-' ) ? ", --no-"
  1239.                                                              : ", --no";
  1240.                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
  1241.             }
  1242.  
  1243.             if( i < 0 )
  1244.             {
  1245.                 psz_spaces[0] = '\n';
  1246.                 i = 0;
  1247.             }
  1248.             else
  1249.             {
  1250.                 psz_spaces[i] = '\0';
  1251.             }
  1252.  
  1253.             if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
  1254.             {
  1255.                 fprintf( stdout, psz_format, psz_short, p_item->psz_name,
  1256.                          psz_prefix, p_item->psz_name, psz_bra, psz_type,
  1257.                          psz_ket, psz_spaces );
  1258.             }
  1259.             else
  1260.             {
  1261.                 fprintf( stdout, psz_format, psz_short, p_item->psz_name,
  1262.                          "", "", psz_bra, psz_type, psz_ket, psz_spaces );
  1263.             }
  1264.  
  1265.             psz_spaces[i] = ' ';
  1266.  
  1267.             /* We wrap the rest of the output */
  1268.             sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
  1269.             psz_text = psz_buffer;
  1270.             while( *psz_text )
  1271.             {
  1272.                 char *psz_parser, *psz_word;
  1273.                 int i_end = strlen( psz_text );
  1274.  
  1275.                 /* If the remaining text fits in a line, print it. */
  1276.                 if( i_end <= i_width )
  1277.                 {
  1278.                     fprintf( stdout, "%s\n", psz_text );
  1279.                     break;
  1280.                 }
  1281.  
  1282.                 /* Otherwise, eat as many words as possible */
  1283.                 psz_parser = psz_text;
  1284.                 do
  1285.                 {
  1286.                     psz_word = psz_parser;
  1287.                     psz_parser = strchr( psz_word, ' ' );
  1288.                     /* If no space was found, we reached the end of the text
  1289.                      * block; otherwise, we skip the space we just found. */
  1290.                     psz_parser = psz_parser ? psz_parser + 1
  1291.                                             : psz_text + i_end;
  1292.  
  1293.                 } while( psz_parser - psz_text <= i_width );
  1294.  
  1295.                 /* We cut a word in one of these cases:
  1296.                  *  - it's the only word in the line and it's too long.
  1297.                  *  - we used less than 80% of the width and the word we are
  1298.                  *    going to wrap is longer than 40% of the width, and even
  1299.                  *    if the word would have fit in the next line. */
  1300.                 if( psz_word == psz_text
  1301.                      || ( psz_word - psz_text < 80 * i_width / 100
  1302.                            && psz_parser - psz_word > 40 * i_width / 100 ) )
  1303.                 {
  1304.                     char c = psz_text[i_width];
  1305.                     psz_text[i_width] = '\0';
  1306.                     fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
  1307.                     psz_text += i_width;
  1308.                     psz_text[0] = c;
  1309.                 }
  1310.                 else
  1311.                 {
  1312.                     psz_word[-1] = '\0';
  1313.                     fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
  1314.                     psz_text = psz_word;
  1315.                 }
  1316.             }
  1317.         }
  1318.     }
  1319.  
  1320.     /* Release the module list */
  1321.     vlc_list_release( p_list );
  1322.  
  1323. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1324.     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
  1325.     getchar();
  1326. #endif
  1327. }
  1328.  
  1329. /*****************************************************************************
  1330.  * ListModules: list the available modules with their description
  1331.  *****************************************************************************
  1332.  * Print a list of all available modules (builtins and plugins) and a short
  1333.  * description for each one.
  1334.  *****************************************************************************/
  1335. static void ListModules( vlc_t *p_this )
  1336. {
  1337.     vlc_list_t *p_list;
  1338.     module_t *p_parser;
  1339.     char psz_spaces[22];
  1340.     int i_index;
  1341.  
  1342.     memset( psz_spaces, ' ', 22 );
  1343.  
  1344. #ifdef WIN32
  1345.     ShowConsole();
  1346. #endif
  1347.  
  1348.     /* Usage */
  1349.     fprintf( stdout, _("Usage: %s [options] [items]...\n\n"),
  1350.                      p_this->p_vlc->psz_object_name );
  1351.  
  1352.     fprintf( stdout, _("[module]              [description]\n") );
  1353.  
  1354.     /* List all modules */
  1355.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  1356.  
  1357.     /* Enumerate each module */
  1358.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  1359.     {
  1360.         int i;
  1361.  
  1362.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  1363.  
  1364.         /* Nasty hack, but right now I'm too tired to think about a nice
  1365.          * solution */
  1366.         i = 22 - strlen( p_parser->psz_object_name ) - 1;
  1367.         if( i < 0 ) i = 0;
  1368.         psz_spaces[i] = 0;
  1369.  
  1370.         fprintf( stdout, "  %s%s %s\n", p_parser->psz_object_name,
  1371.                          psz_spaces, p_parser->psz_longname );
  1372.  
  1373.         psz_spaces[i] = ' ';
  1374.     }
  1375.  
  1376.     vlc_list_release( p_list );
  1377.  
  1378. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1379.     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
  1380.     getchar();
  1381. #endif
  1382. }
  1383.  
  1384. /*****************************************************************************
  1385.  * Version: print complete program version
  1386.  *****************************************************************************
  1387.  * Print complete program version and build number.
  1388.  *****************************************************************************/
  1389. static void Version( void )
  1390. {
  1391. #ifdef WIN32
  1392.     ShowConsole();
  1393. #endif
  1394.  
  1395.     fprintf( stdout, VERSION_MESSAGE "\n" );
  1396.     fprintf( stdout,
  1397.       _("This program comes with NO WARRANTY, to the extent permitted by "
  1398.         "law.\nYou may redistribute it under the terms of the GNU General "
  1399.         "Public License;\nsee the file named COPYING for details.\n"
  1400.         "Written by the VideoLAN team at Ecole Centrale, Paris.\n") );
  1401.  
  1402. #ifdef WIN32        /* Pause the console because it's destroyed when we exit */
  1403.     fprintf( stdout, _("\nPress the RETURN key to continue...\n") );
  1404.     getchar();
  1405. #endif
  1406. }
  1407.  
  1408. /*****************************************************************************
  1409.  * ShowConsole: On Win32, create an output console for debug messages
  1410.  *****************************************************************************
  1411.  * This function is useful only on Win32.
  1412.  *****************************************************************************/
  1413. #ifdef WIN32 /*  */
  1414. static void ShowConsole( void )
  1415. {
  1416. #   ifndef UNDER_CE
  1417.     AllocConsole();
  1418.     freopen( "CONOUT$", "w", stdout );
  1419.     freopen( "CONOUT$", "w", stderr );
  1420.     freopen( "CONIN$", "r", stdin );
  1421. #   endif
  1422.     return;
  1423. }
  1424. #endif
  1425.  
  1426. /*****************************************************************************
  1427.  * ConsoleWidth: Return the console width in characters
  1428.  *****************************************************************************
  1429.  * We use the stty shell command to get the console width; if this fails or
  1430.  * if the width is less than 80, we default to 80.
  1431.  *****************************************************************************/
  1432. static int ConsoleWidth( void )
  1433. {
  1434.     int i_width = 80;
  1435.  
  1436. #ifndef WIN32
  1437.     char buf[20], *psz_parser;
  1438.     FILE *file;
  1439.     int i_ret;
  1440.  
  1441.     file = popen( "stty size 2>/dev/null", "r" );
  1442.     if( file )
  1443.     {
  1444.         i_ret = fread( buf, 1, 20, file );
  1445.         if( i_ret > 0 )
  1446.         {
  1447.             buf[19] = '\0';
  1448.             psz_parser = strchr( buf, ' ' );
  1449.             if( psz_parser )
  1450.             {
  1451.                 i_ret = atoi( psz_parser + 1 );
  1452.                 if( i_ret >= 80 )
  1453.                 {
  1454.                     i_width = i_ret;
  1455.                 }
  1456.             }
  1457.         }
  1458.  
  1459.         pclose( file );
  1460.     }
  1461. #endif
  1462.  
  1463.     return i_width;
  1464. }
  1465.